home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / DepthOfField / DepthOfField.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  45.6 KB  |  1,027 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: DepthOfField.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10.  
  11. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  12. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  13.  
  14.  
  15. //--------------------------------------------------------------------------------------
  16. // Vertex format
  17. //--------------------------------------------------------------------------------------
  18. struct VERTEX 
  19. {
  20.     D3DXVECTOR4 pos;
  21.     DWORD       clr;
  22.     D3DXVECTOR2 tex1;
  23.     D3DXVECTOR2 tex2;
  24.     D3DXVECTOR2 tex3;
  25.     D3DXVECTOR2 tex4;
  26.     D3DXVECTOR2 tex5;
  27.     D3DXVECTOR2 tex6;
  28.  
  29.     static const DWORD FVF;
  30. };
  31. const DWORD VERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX6;
  32.  
  33.  
  34. //--------------------------------------------------------------------------------------
  35. // Global variables
  36. //--------------------------------------------------------------------------------------
  37. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  38. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  39. CFirstPersonCamera      g_Camera;               // A model viewing camera
  40. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  41. CDXUTDialog             g_HUD;                  // dialog for standard controls
  42. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  43.  
  44. VERTEX                  g_Vertex[4];
  45.  
  46. LPDIRECT3DTEXTURE9      g_pFullScreenTexture;
  47. LPD3DXRENDERTOSURFACE   g_pRenderToSurface;
  48. LPDIRECT3DSURFACE9      g_pFullScreenTextureSurf;
  49.  
  50. LPD3DXMESH              g_pScene1Mesh;
  51. LPDIRECT3DTEXTURE9      g_pScene1MeshTexture;
  52. LPD3DXMESH              g_pScene2Mesh;
  53. LPDIRECT3DTEXTURE9      g_pScene2MeshTexture;
  54. int                     g_nCurrentScene;
  55. LPD3DXEFFECT            g_pEffect;
  56.  
  57. D3DXVECTOR4             g_vFocalPlane;
  58. double                  g_fChangeTime;
  59. int                     g_nShowMode;
  60. DWORD                   g_dwBackgroundColor;
  61.  
  62. D3DVIEWPORT9            g_ViewportFB;
  63. D3DVIEWPORT9            g_ViewportOffscreen;
  64.  
  65. FLOAT                   g_fBlurConst;
  66. DWORD                   g_TechniqueIndex;
  67.  
  68. D3DXHANDLE              g_hFocalPlane;
  69. D3DXHANDLE              g_hWorld;
  70. D3DXHANDLE              g_hWorldView;
  71. D3DXHANDLE              g_hWorldViewProjection;
  72. D3DXHANDLE              g_hMeshTexture;
  73. D3DXHANDLE              g_hTechWorldWithBlurFactor;
  74. D3DXHANDLE              g_hTechShowBlurFactor;
  75. D3DXHANDLE              g_hTechShowUnmodified;
  76. D3DXHANDLE              g_hTech[5];
  77.  
  78. static CHAR* g_TechniqueNames[] = { "UsePS20ThirteenLookups",
  79.                                     "UsePS20SevenLookups",
  80.                                     "UsePS20SixTexcoords",
  81.                                     "UsePS11FourTexcoordsNoRings",
  82.                                     "UsePS11FourTexcoordsWithRings" };
  83. const DWORD g_TechniqueCount = sizeof(g_TechniqueNames)/sizeof(LPCSTR);
  84.  
  85.  
  86.  
  87. //--------------------------------------------------------------------------------------
  88. // UI control IDs
  89. //--------------------------------------------------------------------------------------
  90. #define IDC_TOGGLEFULLSCREEN    1
  91. #define IDC_TOGGLEREF           3
  92. #define IDC_CHANGEDEVICE        4
  93. #define IDC_CHANGE_SCENE        5
  94. #define IDC_CHANGE_TECHNIQUE    6
  95. #define IDC_SHOW_BLUR           7
  96. #define IDC_CHANGE_BLUR         8
  97. #define IDC_CHANGE_FOCAL        9
  98. #define IDC_CHANGE_BLUR_STATIC  10
  99. #define IDC_SHOW_UNBLURRED      11
  100. #define IDC_SHOW_NORMAL         12
  101. #define IDC_CHANGE_FOCAL_STATIC 13
  102.  
  103.  
  104.  
  105. //--------------------------------------------------------------------------------------
  106. // Forward declarations 
  107. //--------------------------------------------------------------------------------------
  108. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  109. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  110. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  111. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  112. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  113. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  114. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  115. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  116. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  117. void    CALLBACK OnLostDevice();
  118. void    CALLBACK OnDestroyDevice();
  119.  
  120. void    InitApp();
  121. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  122. void    RenderText();
  123. void    SetupQuad( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  124. HRESULT UpdateTechniqueSpecificVariables( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  125.  
  126.  
  127. //--------------------------------------------------------------------------------------
  128. // Entry point to the program. Initializes everything and goes into a message processing 
  129. // loop. Idle time is used to render the scene.
  130. //--------------------------------------------------------------------------------------
  131. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  132. {
  133.     // Set the callback functions. These functions allow the sample framework to notify
  134.     // the application about device changes, user input, and windows messages.  The 
  135.     // callbacks are optional so you need only set callbacks for events you're interested 
  136.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  137.     // framework won't be able to reset your device since the application must first 
  138.     // release all device resources before resetting.  Likewise, if you don't handle the 
  139.     // device created/destroyed callbacks then the sample framework won't be able to 
  140.     // recreate your device resources.
  141.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  142.     DXUTSetCallbackDeviceReset( OnResetDevice );
  143.     DXUTSetCallbackDeviceLost( OnLostDevice );
  144.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  145.     DXUTSetCallbackMsgProc( MsgProc );
  146.     DXUTSetCallbackKeyboard( KeyboardProc );
  147.     DXUTSetCallbackFrameRender( OnFrameRender );
  148.     DXUTSetCallbackFrameMove( OnFrameMove );
  149.  
  150.     // Show the cursor and clip it when in full screen
  151.     DXUTSetCursorSettings( true, true );
  152.  
  153.     InitApp();
  154.  
  155.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  156.     // device for the application. Calling each of these functions is optional, but they
  157.     // allow you to set several options which control the behavior of the framework.
  158.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  159.     DXUTCreateWindow( L"DepthOfField" );
  160.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  161.  
  162.     // Pass control to the sample framework for handling the message pump and 
  163.     // dispatching render calls. The sample framework will call your FrameMove 
  164.     // and FrameRender callback when there is idle time between handling window messages.
  165.     DXUTMainLoop();
  166.  
  167.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  168.     // appropriate callback functions and therefore don't require any cleanup code here.
  169.  
  170.     return DXUTGetExitCode();
  171. }
  172.  
  173.  
  174. //--------------------------------------------------------------------------------------
  175. // Initialize the app 
  176. //--------------------------------------------------------------------------------------
  177. void InitApp()
  178. {
  179.     g_pFont = NULL;
  180.  
  181.     g_pFullScreenTexture = NULL;
  182.     g_pFullScreenTextureSurf = NULL;
  183.     g_pRenderToSurface = NULL;
  184.     g_pEffect = NULL;
  185.  
  186.     g_vFocalPlane = D3DXVECTOR4(0.0f, 0.0f, 1.0f, -2.5f);
  187.     g_fChangeTime = 0.0f;
  188.  
  189.     g_pScene1Mesh = NULL;
  190.     g_pScene1MeshTexture = NULL;
  191.     g_pScene2Mesh = NULL;
  192.     g_pScene2MeshTexture = NULL;
  193.     g_nCurrentScene = 1;
  194.  
  195.     g_nShowMode = 0;
  196.     g_bShowHelp = TRUE;
  197.     g_dwBackgroundColor = 0x00003F3F;
  198.  
  199.     g_fBlurConst = 4.0f;
  200.     g_TechniqueIndex = 0;
  201.  
  202.     g_hFocalPlane = NULL;
  203.     g_hWorld = NULL;
  204.     g_hWorldView = NULL;
  205.     g_hWorldViewProjection = NULL;
  206.     g_hMeshTexture = NULL;
  207.     g_hTechWorldWithBlurFactor = NULL;
  208.     g_hTechShowBlurFactor = NULL;
  209.     g_hTechShowUnmodified = NULL;
  210.     ZeroMemory( g_hTech, sizeof(g_hTech) );
  211.  
  212.     // Initialize dialogs
  213.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  214.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  215.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  216.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  217.  
  218.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; 
  219.     g_SampleUI.AddButton( IDC_CHANGE_SCENE, L"Change Scene", 35, iY += 24, 125, 22, 'P' );
  220.     g_SampleUI.AddButton( IDC_CHANGE_TECHNIQUE, L"Change Technique", 35, iY += 24, 125, 22, 'N' );
  221.     g_SampleUI.AddRadioButton( IDC_SHOW_NORMAL, 1, L"Show Normal", 35, iY += 24, 125, 22, true );
  222.     g_SampleUI.AddRadioButton( IDC_SHOW_BLUR, 1, L"Show Blur Factor", 35, iY += 24, 125, 22 );
  223.     g_SampleUI.AddRadioButton( IDC_SHOW_UNBLURRED, 1, L"Show Unblurred", 35, iY += 24, 125, 22 );
  224.  
  225.     iY += 24;
  226.     WCHAR sz[100];
  227.     _snwprintf( sz, 100, L"Focal Distance: %0.2f", -g_vFocalPlane.w ); sz[99] = 0;
  228.     g_SampleUI.AddStatic( IDC_CHANGE_FOCAL_STATIC, sz, 35, iY += 24, 125, 22 );
  229.     g_SampleUI.AddSlider( IDC_CHANGE_FOCAL, 50, iY += 24, 100, 22, 0, 100, (int) (-g_vFocalPlane.w*10.0f) );
  230.  
  231.     iY += 24;
  232.     _snwprintf( sz, 100, L"Blur Factor: %0.2f", g_fBlurConst ); sz[99] = 0;
  233.     g_SampleUI.AddStatic( IDC_CHANGE_BLUR_STATIC, sz, 35, iY += 24, 125, 22 );
  234.     g_SampleUI.AddSlider( IDC_CHANGE_BLUR, 50, iY += 24, 100, 22, 0, 100, (int) (g_fBlurConst*10.0f) );
  235. }
  236.  
  237.  
  238. //--------------------------------------------------------------------------------------
  239. // Called during device initialization, this code checks the device for some 
  240. // minimum set of capabilities, and rejects those that don't pass by returning false.
  241. //--------------------------------------------------------------------------------------
  242. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  243.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  244. {
  245.     // Skip backbuffer formats that don't support alpha blending
  246.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  247.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  248.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  249.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  250.         return false;
  251.  
  252.     // Must support pixel shader 1.1
  253.     if( pCaps->PixelShaderVersion < D3DPS_VERSION( 1, 1 ) )
  254.         return false;
  255.  
  256.     return true;
  257. }
  258.  
  259.  
  260. //--------------------------------------------------------------------------------------
  261. // This callback function is called immediately before a device is created to allow the 
  262. // application to modify the device settings. The supplied pDeviceSettings parameter 
  263. // contains the settings that the framework has selected for the new device, and the 
  264. // application can make any desired changes directly to this structure.  Note however that 
  265. // the sample framework will not correct invalid device settings so care must be taken 
  266. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  267. //--------------------------------------------------------------------------------------
  268. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  269. {
  270.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  271.     // then switch to SWVP.
  272.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  273.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  274.     {
  275.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  276.     }
  277.     else
  278.     {
  279.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  280.     }
  281.  
  282.     // This application is designed to work on a pure device by not using 
  283.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  284.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  285.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  286.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  287.  
  288.     // Debugging vertex shaders requires either REF or software vertex processing 
  289.     // and debugging pixel shaders requires REF.  
  290. #ifdef DEBUG_VS
  291.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  292.     {
  293.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  294.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  295.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  296.     }
  297. #endif
  298. #ifdef DEBUG_PS
  299.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  300. #endif
  301. }
  302.  
  303.  
  304. //--------------------------------------------------------------------------------------
  305. // This callback function will be called immediately after the Direct3D device has been 
  306. // created, which will happen during application initialization and windowed/full screen 
  307. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  308. // resources need to be reloaded whenever the device is destroyed. Resources created  
  309. // here should be released in the OnDestroyDevice callback. 
  310. //--------------------------------------------------------------------------------------
  311. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  312. {
  313.     WCHAR str[MAX_PATH];
  314.     HRESULT hr;
  315.  
  316.     // Initialize the font
  317.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  318.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  319.                          L"Arial", &g_pFont ) );
  320.  
  321.     // Load the meshs
  322.     V_RETURN( LoadMesh( pd3dDevice, TEXT("tiger\\tiger.x"), &g_pScene1Mesh ) );
  323.     V_RETURN( LoadMesh( pd3dDevice, TEXT("misc\\sphere.x"), &g_pScene2Mesh ) );
  324.  
  325.     // Load the mesh textures
  326.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"tiger\\tiger.bmp" ) );
  327.     V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, str, &g_pScene1MeshTexture) );
  328.  
  329.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"earth\\earth.bmp" ) );
  330.     V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, str, &g_pScene2MeshTexture) );
  331.  
  332.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  333.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  334.     // processing, and debugging pixel shaders requires REF.  The 
  335.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  336.     // shader debugger.  It enables source level debugging, prevents instruction 
  337.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  338.     // against the next higher available software target, which ensures that the 
  339.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  340.     // flags will cause slower rendering since the shaders will be unoptimized and 
  341.     // forced into software.  See the DirectX documentation for more information about 
  342.     // using the shader debugger.
  343.     DWORD dwShaderFlags = 0;
  344.     #ifdef DEBUG_VS
  345.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  346.     #endif
  347.     #ifdef DEBUG_PS
  348.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  349.     #endif
  350.  
  351.     // Read the D3DX effect file
  352.     // If this fails, there should be debug output as to 
  353.     // they the .fx file failed to compile
  354.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"DepthOfField.fx" ) );
  355.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  356.                                         NULL, &g_pEffect, NULL ) );
  357.  
  358.     return S_OK;
  359. }
  360.  
  361.  
  362. //--------------------------------------------------------------------------------------
  363. // This function loads the mesh and ensures the mesh has normals; it also optimizes the 
  364. // mesh for the graphics card's vertex cache, which improves performance by organizing 
  365. // the internal triangle list for less cache misses.
  366. //--------------------------------------------------------------------------------------
  367. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh )
  368. {
  369.     ID3DXMesh* pMesh = NULL;
  370.     WCHAR str[MAX_PATH];
  371.     HRESULT hr;
  372.  
  373.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  374.     // sample we'll ignore the X file's embedded materials since we know 
  375.     // exactly the model we're loading.  See the mesh samples such as
  376.     // "OptimizedMesh" for a more generic mesh loading example.
  377.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );
  378.  
  379.     V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) );
  380.  
  381.     DWORD *rgdwAdjacency = NULL;
  382.  
  383.     // Make sure there are normals which are required for lighting
  384.     if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
  385.     {
  386.         ID3DXMesh* pTempMesh;
  387.         V( pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  388.                                   pMesh->GetFVF() | D3DFVF_NORMAL, 
  389.                                   pd3dDevice, &pTempMesh ) );
  390.         V( D3DXComputeNormals( pTempMesh, NULL ) );
  391.  
  392.         SAFE_RELEASE( pMesh );
  393.         pMesh = pTempMesh;
  394.     }
  395.  
  396.     // Optimize the mesh for this graphics card's vertex cache 
  397.     // so when rendering the mesh's triangle list the vertices will 
  398.     // cache hit more often so it won't have to re-execute the vertex shader 
  399.     // on those vertices so it will improve perf.     
  400.     rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
  401.     if( rgdwAdjacency == NULL )
  402.         return E_OUTOFMEMORY;
  403.     V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  404.     V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  405.     delete []rgdwAdjacency;
  406.  
  407.     *ppMesh = pMesh;
  408.  
  409.     return S_OK;
  410. }
  411.  
  412.  
  413. //--------------------------------------------------------------------------------------
  414. // This callback function will be called immediately after the Direct3D device has been 
  415. // reset, which will happen after a lost device scenario. This is the best location to 
  416. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  417. // the device is lost. Resources created here should be released in the OnLostDevice 
  418. // callback. 
  419. //--------------------------------------------------------------------------------------
  420. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  421.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  422. {
  423.     HRESULT hr;
  424.  
  425.     if( g_pFont )
  426.         V_RETURN( g_pFont->OnResetDevice() );
  427.     if( g_pEffect )
  428.         V_RETURN( g_pEffect->OnResetDevice() );
  429.  
  430.     // Setup the camera with view & projection matrix
  431.     D3DXVECTOR3 vecEye(1.3f, 1.1f, -3.3f);
  432.     D3DXVECTOR3 vecAt (0.75f, 0.9f, -2.5f);
  433.     g_Camera.SetViewParams( &vecEye, &vecAt );
  434.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  435.     g_Camera.SetProjParams( D3DXToRadian(60.0f), fAspectRatio, 0.5f, 100.0f );
  436.  
  437.     pd3dDevice->GetViewport(&g_ViewportFB);
  438.  
  439.     // Backbuffer viewport is identical to frontbuffer, except starting at 0, 0
  440.     g_ViewportOffscreen = g_ViewportFB;
  441.     g_ViewportOffscreen.X = 0;
  442.     g_ViewportOffscreen.Y = 0;
  443.  
  444.     // Create fullscreen renders target texture
  445.     hr = D3DXCreateTexture( pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 
  446.                             1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pFullScreenTexture);
  447.     if( FAILED(hr) )
  448.     {
  449.         // Fallback to a non-RT texture
  450.         V_RETURN( D3DXCreateTexture( pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 
  451.                                      1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pFullScreenTexture ) );
  452.     }
  453.  
  454.     D3DSURFACE_DESC desc;
  455.     g_pFullScreenTexture->GetSurfaceLevel(0, &g_pFullScreenTextureSurf);
  456.     g_pFullScreenTextureSurf->GetDesc(&desc);
  457.  
  458.     // Create a ID3DXRenderToSurface to help render to a texture on cards 
  459.     // that don't support render targets
  460.     V_RETURN( D3DXCreateRenderToSurface( pd3dDevice, desc.Width, desc.Height, 
  461.                                          desc.Format, TRUE, D3DFMT_D16, &g_pRenderToSurface ) );
  462.  
  463.     // clear the surface alpha to 0 so that it does not bleed into a "blurry" background
  464.     //   this is possible because of the avoidance of blurring in a non-blurred texel
  465.     if(SUCCEEDED(g_pRenderToSurface->BeginScene(g_pFullScreenTextureSurf, NULL)))
  466.     {
  467.         pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00, 1.0f, 0);
  468.         g_pRenderToSurface->EndScene( 0 );
  469.     }
  470.  
  471.     D3DXCOLOR colorWhite(1.0f, 1.0f, 1.0f, 1.0f);
  472.     D3DXCOLOR colorBlack(0.0f, 0.0f, 0.0f, 1.0f);
  473.     D3DXCOLOR colorAmbient(0.25f, 0.25f, 0.25f, 1.0f);
  474.  
  475.     // Get D3DXHANDLEs to the parameters/techniques that are set every frame so 
  476.     // D3DX doesn't spend time doing string compares.  Doing this likely won't affect
  477.     // the perf of this simple sample but it should be done in complex engine.
  478.     g_hFocalPlane               = g_pEffect->GetParameterByName( NULL, "vFocalPlane" );
  479.     g_hWorld                    = g_pEffect->GetParameterByName( NULL, "mWorld" );
  480.     g_hWorldView                = g_pEffect->GetParameterByName( NULL, "mWorldView" );
  481.     g_hWorldViewProjection      = g_pEffect->GetParameterByName( NULL, "mWorldViewProjection" );
  482.     g_hMeshTexture              = g_pEffect->GetParameterByName( NULL, "MeshTexture" );
  483.     g_hTechWorldWithBlurFactor  = g_pEffect->GetTechniqueByName("WorldWithBlurFactor");
  484.     g_hTechShowBlurFactor       = g_pEffect->GetTechniqueByName("ShowBlurFactor");
  485.     g_hTechShowUnmodified       = g_pEffect->GetTechniqueByName("ShowUnmodified");
  486.     for( int i=0; i<5; i++ )
  487.         g_hTech[i] = g_pEffect->GetTechniqueByName( g_TechniqueNames[i] );
  488.  
  489.     // Set the vars in the effect that doesn't change each frame
  490.     V_RETURN( g_pEffect->SetVector("MaterialAmbientColor", (D3DXVECTOR4*)&colorAmbient) );
  491.     V_RETURN( g_pEffect->SetVector("MaterialDiffuseColor", (D3DXVECTOR4*)&colorWhite) );
  492.     V_RETURN( g_pEffect->SetTexture("RenderTargetTexture", g_pFullScreenTexture) );
  493.  
  494.     // Check if the current technique is valid for the new device/settings
  495.     // Start from the current technique, increment until we find one we can use.
  496.     DWORD OriginalTechnique = g_TechniqueIndex;
  497.     do
  498.     {
  499.         D3DXHANDLE hTech = g_pEffect->GetTechniqueByName( g_TechniqueNames[g_TechniqueIndex] );
  500.         if( SUCCEEDED( g_pEffect->ValidateTechnique( hTech ) ) )
  501.             break;
  502.  
  503.         g_TechniqueIndex++;
  504.  
  505.         if( g_TechniqueIndex == g_TechniqueCount )
  506.             g_TechniqueIndex = 0;
  507.     } 
  508.     while( OriginalTechnique != g_TechniqueIndex );
  509.  
  510.     V_RETURN( UpdateTechniqueSpecificVariables( pBackBufferSurfaceDesc ) );
  511.  
  512.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  513.     g_HUD.SetSize( 170, 170 );
  514.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-300 );
  515.     g_SampleUI.SetSize( 170, 250 );
  516.  
  517.     return S_OK;
  518. }
  519.  
  520.  
  521. //--------------------------------------------------------------------------------------
  522. // Certain parameters need to be specified for specific techniques
  523. //--------------------------------------------------------------------------------------
  524. HRESULT UpdateTechniqueSpecificVariables( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  525. {
  526.     LPCSTR strInputArrayName, strOutputArrayName;
  527.     int nNumKernelEntries;
  528.     HRESULT hr;
  529.     D3DXHANDLE hAnnotation;
  530.  
  531.     // Create the post-process quad and set the texcoords based on the blur factor
  532.     SetupQuad( pBackBufferSurfaceDesc );
  533.  
  534.     // Get the handle to the current technique
  535.     D3DXHANDLE hTech = g_pEffect->GetTechniqueByName(g_TechniqueNames[g_TechniqueIndex]);   
  536.     if(hTech == NULL)
  537.         return S_FALSE; // This will happen if the technique doesn't have this annotation
  538.  
  539.     // Get the value of the annotation int named "NumKernelEntries" inside the technique
  540.     hAnnotation = g_pEffect->GetAnnotationByName(hTech, "NumKernelEntries");
  541.     if( hAnnotation == NULL )
  542.         return S_FALSE; // This will happen if the technique doesn't have this annotation
  543.     V_RETURN( g_pEffect->GetInt(hAnnotation, &nNumKernelEntries) );
  544.  
  545.     // Get the value of the annotation string named "KernelInputArray" inside the technique
  546.     hAnnotation = g_pEffect->GetAnnotationByName(hTech, "KernelInputArray");
  547.     if( hAnnotation == NULL )
  548.         return S_FALSE; // This will happen if the technique doesn't have this annotation
  549.     V_RETURN( g_pEffect->GetString( hAnnotation, &strInputArrayName) );
  550.  
  551.     // Get the value of the annotation string named "KernelOutputArray" inside the technique
  552.     hAnnotation = g_pEffect->GetAnnotationByName(hTech, "KernelOutputArray");
  553.     if( hAnnotation == NULL )
  554.         return S_FALSE; // This will happen if the technique doesn't have this annotation
  555.     if( FAILED( hr = g_pEffect->GetString( hAnnotation, &strOutputArrayName) ) )
  556.         return hr;
  557.  
  558.     // Create a array to store the input array
  559.     D3DXVECTOR2* aKernel = new D3DXVECTOR2[nNumKernelEntries];
  560.     if (aKernel == NULL)
  561.         return E_OUTOFMEMORY;
  562.  
  563.     // Get the input array
  564.     V_RETURN( g_pEffect->GetValue(strInputArrayName, aKernel, sizeof(D3DXVECTOR2) * nNumKernelEntries) );
  565.  
  566.     // Get the size of the texture
  567.     D3DSURFACE_DESC desc;
  568.     g_pFullScreenTextureSurf->GetDesc(&desc);
  569.  
  570.     // Calculate the scale factor to convert the input array to screen space
  571.     FLOAT fWidthMod = g_fBlurConst / (FLOAT)desc.Width ;
  572.     FLOAT fHeightMod = g_fBlurConst / (FLOAT)desc.Height;
  573.  
  574.     // Scale the effect's kernel from pixel space to tex coord space
  575.     // In pixel space 1 unit = one pixel and in tex coord 1 unit = width/height of texture
  576.     for( int iEntry = 0; iEntry < nNumKernelEntries; iEntry++ )
  577.     {
  578.         aKernel[iEntry].x *= fWidthMod;
  579.         aKernel[iEntry].y *= fHeightMod;
  580.     }
  581.  
  582.     // Pass the updated array values to the effect file
  583.     V_RETURN( g_pEffect->SetValue(strOutputArrayName, aKernel, sizeof(D3DXVECTOR2) * nNumKernelEntries) );
  584.  
  585.     SAFE_DELETE_ARRAY( aKernel );
  586.  
  587.     return S_OK;
  588. }
  589.  
  590.  
  591. //--------------------------------------------------------------------------------------
  592. // Sets up a quad to render the fullscreen render target to the backbuffer
  593. // so it can run a fullscreen pixel shader pass that blurs based
  594. // on the depth of the objects.  It set the texcoords based on the blur factor
  595. //--------------------------------------------------------------------------------------
  596. void SetupQuad( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  597. {
  598.     D3DSURFACE_DESC desc;
  599.     g_pFullScreenTextureSurf->GetDesc(&desc);
  600.  
  601.     FLOAT fWidth5 = (FLOAT)pBackBufferSurfaceDesc->Width - 0.5f;
  602.     FLOAT fHeight5 = (FLOAT)pBackBufferSurfaceDesc->Height - 0.5f;
  603.  
  604.     FLOAT fHalf = g_fBlurConst;
  605.     FLOAT fOffOne = fHalf * 0.5f;
  606.     FLOAT fOffTwo = fOffOne * sqrtf(3.0f);
  607.  
  608.     FLOAT fTexWidth1 = (FLOAT)pBackBufferSurfaceDesc->Width / (FLOAT)desc.Width;
  609.     FLOAT fTexHeight1 = (FLOAT)pBackBufferSurfaceDesc->Height / (FLOAT)desc.Height;
  610.  
  611.     FLOAT fWidthMod = 1.0f / (FLOAT)desc.Width ;
  612.     FLOAT fHeightMod = 1.0f / (FLOAT)desc.Height;
  613.  
  614.     // Create vertex buffer.  
  615.     // g_Vertex[0].tex1 == full texture coverage
  616.     // g_Vertex[0].tex2 == full texture coverage, but shifted y by -fHalf*fHeightMod
  617.     // g_Vertex[0].tex3 == full texture coverage, but shifted x by -fOffTwo*fWidthMod & y by -fOffOne*fHeightMod
  618.     // g_Vertex[0].tex4 == full texture coverage, but shifted x by +fOffTwo*fWidthMod & y by -fOffOne*fHeightMod
  619.     // g_Vertex[0].tex5 == full texture coverage, but shifted x by -fOffTwo*fWidthMod & y by +fOffOne*fHeightMod
  620.     // g_Vertex[0].tex6 == full texture coverage, but shifted x by +fOffTwo*fWidthMod & y by +fOffOne*fHeightMod
  621.     g_Vertex[0].pos = D3DXVECTOR4(fWidth5, -0.5f, 0.0f, 1.0f);
  622.     g_Vertex[0].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  623.     g_Vertex[0].tex1 = D3DXVECTOR2(fTexWidth1, 0.0f);
  624.     g_Vertex[0].tex2 = D3DXVECTOR2(fTexWidth1, 0.0f - fHalf*fHeightMod);
  625.     g_Vertex[0].tex3 = D3DXVECTOR2(fTexWidth1 - fOffTwo*fWidthMod, 0.0f - fOffOne*fHeightMod);
  626.     g_Vertex[0].tex4 = D3DXVECTOR2(fTexWidth1 + fOffTwo*fWidthMod, 0.0f - fOffOne*fHeightMod);
  627.     g_Vertex[0].tex5 = D3DXVECTOR2(fTexWidth1 - fOffTwo*fWidthMod, 0.0f + fOffOne*fHeightMod);
  628.     g_Vertex[0].tex6 = D3DXVECTOR2(fTexWidth1 + fOffTwo*fWidthMod, 0.0f + fOffOne*fHeightMod);
  629.  
  630.     g_Vertex[1].pos = D3DXVECTOR4(fWidth5, fHeight5, 0.0f, 1.0f);
  631.     g_Vertex[1].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  632.     g_Vertex[1].tex1 = D3DXVECTOR2(fTexWidth1, fTexHeight1);
  633.     g_Vertex[1].tex2 = D3DXVECTOR2(fTexWidth1, fTexHeight1 - fHalf*fHeightMod);
  634.     g_Vertex[1].tex3 = D3DXVECTOR2(fTexWidth1 - fOffTwo*fWidthMod, fTexHeight1 - fOffOne*fHeightMod);
  635.     g_Vertex[1].tex4 = D3DXVECTOR2(fTexWidth1 + fOffTwo*fWidthMod, fTexHeight1 - fOffOne*fHeightMod);
  636.     g_Vertex[1].tex5 = D3DXVECTOR2(fTexWidth1 - fOffTwo*fWidthMod, fTexHeight1 + fOffOne*fHeightMod);
  637.     g_Vertex[1].tex6 = D3DXVECTOR2(fTexWidth1 + fOffTwo*fWidthMod, fTexHeight1 + fOffOne*fHeightMod);
  638.  
  639.     g_Vertex[2].pos = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
  640.     g_Vertex[2].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  641.     g_Vertex[2].tex1 = D3DXVECTOR2(0.0f, 0.0f);
  642.     g_Vertex[2].tex2 = D3DXVECTOR2(0.0f, 0.0f - fHalf*fHeightMod);
  643.     g_Vertex[2].tex3 = D3DXVECTOR2(0.0f - fOffTwo*fWidthMod, 0.0f - fOffOne*fHeightMod);
  644.     g_Vertex[2].tex4 = D3DXVECTOR2(0.0f + fOffTwo*fWidthMod, 0.0f - fOffOne*fHeightMod);
  645.     g_Vertex[2].tex5 = D3DXVECTOR2(0.0f - fOffTwo*fWidthMod, 0.0f + fOffOne*fHeightMod);
  646.     g_Vertex[2].tex6 = D3DXVECTOR2(0.0f + fOffTwo*fWidthMod, 0.0f + fOffOne*fHeightMod);
  647.  
  648.     g_Vertex[3].pos = D3DXVECTOR4(-0.5f, fHeight5, 0.0f, 1.0f);
  649.     g_Vertex[3].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  650.     g_Vertex[3].tex1 = D3DXVECTOR2(0.0f, fTexHeight1);
  651.     g_Vertex[3].tex2 = D3DXVECTOR2(0.0f, fTexHeight1 - fHalf*fHeightMod);
  652.     g_Vertex[3].tex3 = D3DXVECTOR2(0.0f - fOffTwo*fWidthMod, fTexHeight1 - fOffOne*fHeightMod);
  653.     g_Vertex[3].tex4 = D3DXVECTOR2(0.0f + fOffTwo*fWidthMod, fTexHeight1 - fOffOne*fHeightMod);
  654.     g_Vertex[3].tex5 = D3DXVECTOR2(0.0f + fOffTwo*fWidthMod, fTexHeight1 + fOffOne*fHeightMod);
  655.     g_Vertex[3].tex6 = D3DXVECTOR2(0.0f - fOffTwo*fWidthMod, fTexHeight1 + fOffOne*fHeightMod);
  656. }
  657.  
  658.  
  659. //--------------------------------------------------------------------------------------
  660. // This callback function will be called once at the beginning of every frame. This is the
  661. // best location for your application to handle updates to the scene, but is not 
  662. // intended to contain actual rendering calls, which should instead be placed in the 
  663. // OnFrameRender callback.  
  664. //--------------------------------------------------------------------------------------
  665. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  666. {
  667.     // Update the camera's position based on user input 
  668.     g_Camera.FrameMove( fElapsedTime );
  669. }
  670.  
  671.  
  672. //--------------------------------------------------------------------------------------
  673. // This callback function will be called at the end of every frame to perform all the 
  674. // rendering calls for the scene, and it will also be called if the window needs to be 
  675. // repainted. After this function has returned, the sample framework will call 
  676. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  677. //--------------------------------------------------------------------------------------
  678. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  679. {
  680.     HRESULT hr;
  681.     UINT iPass, cPasses;
  682.  
  683.     // First render the world on the rendertarget g_pFullScreenTexture. 
  684.     if( SUCCEEDED( g_pRenderToSurface->BeginScene(g_pFullScreenTextureSurf, &g_ViewportOffscreen) ) )
  685.     {
  686.         V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, g_dwBackgroundColor, 1.0f, 0) );
  687.  
  688.         // Get the view & projection matrix from camera
  689.         D3DXMATRIXA16 matWorld;
  690.         D3DXMATRIXA16 matView = *g_Camera.GetViewMatrix();
  691.         D3DXMATRIXA16 matProj = *g_Camera.GetProjMatrix();
  692.         D3DXMATRIXA16 matViewProj = matView * matProj;
  693.  
  694.         // Update focal plane
  695.         g_pEffect->SetVector( g_hFocalPlane, &g_vFocalPlane);
  696.  
  697.         // Set world render technique
  698.         V( g_pEffect->SetTechnique( g_hTechWorldWithBlurFactor ) );
  699.  
  700.         // Set the mesh texture 
  701.         LPD3DXMESH pSceneMesh;
  702.         int nNumObjectsInScene;
  703.         if( g_nCurrentScene == 1 )
  704.         {
  705.             V( g_pEffect->SetTexture( g_hMeshTexture, g_pScene1MeshTexture) );
  706.             pSceneMesh = g_pScene1Mesh;
  707.             nNumObjectsInScene = 25;
  708.         }
  709.         else
  710.         {
  711.             V( g_pEffect->SetTexture( g_hMeshTexture, g_pScene2MeshTexture) );
  712.             pSceneMesh = g_pScene2Mesh;
  713.             nNumObjectsInScene = 3;
  714.         }
  715.  
  716.         static const D3DXVECTOR3 mScene2WorldPos[3] = { D3DXVECTOR3(-0.5f,-0.5f,-0.5f), 
  717.                                                         D3DXVECTOR3( 1.0f, 1.0f, 2.0f), 
  718.                                                         D3DXVECTOR3( 3.0f, 3.0f, 5.0f) };
  719.  
  720.         for(int iObject=0; iObject < nNumObjectsInScene; iObject++)
  721.         {
  722.             // setup the world matrix for the current world
  723.             if( g_nCurrentScene == 1 )
  724.             {
  725.                 D3DXMatrixTranslation( &matWorld, -(iObject % 5)*1.0f, 0.0f, (iObject / 5)*3.0f );
  726.             }
  727.             else
  728.             {
  729.                 D3DXMATRIXA16 matRot, matPos;
  730.                 D3DXMatrixRotationY(&matRot, (float)fTime * 0.66666f);
  731.                 D3DXMatrixTranslation( &matPos, mScene2WorldPos[iObject].x, mScene2WorldPos[iObject].y, mScene2WorldPos[iObject].z );
  732.                 matWorld = matRot * matPos;
  733.             }
  734.  
  735.             // Update effect vars
  736.             D3DXMATRIXA16 matWorldViewProj = matWorld * matViewProj;
  737.             D3DXMATRIXA16 matWorldView = matWorld * matView;
  738.             V( g_pEffect->SetMatrix( g_hWorld, &matWorld) );
  739.             V( g_pEffect->SetMatrix( g_hWorldView, &matWorldView) );
  740.             V( g_pEffect->SetMatrix( g_hWorldViewProjection, &matWorldViewProj) );
  741.  
  742.             // Draw the mesh on the rendertarget
  743.             V( g_pEffect->Begin(&cPasses, 0) );
  744.             for (iPass = 0; iPass < cPasses; iPass++)
  745.             {
  746.                 V( g_pEffect->BeginPass(iPass) );
  747.                 V( pSceneMesh->DrawSubset(0) );
  748.                 V( g_pEffect->EndPass() );
  749.             }
  750.             V( g_pEffect->End() );
  751.         }
  752.  
  753.         V( g_pRenderToSurface->EndScene( 0 ) );
  754.     }
  755.  
  756.     // Clear the backbuffer 
  757.     V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0L ) );
  758.  
  759.     // Begin the scene, rendering to the backbuffer
  760.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  761.     {
  762.         pd3dDevice->SetViewport(&g_ViewportFB);
  763.  
  764.         // Set the post process technique
  765.         switch( g_nShowMode )
  766.         {
  767.             case 0: V( g_pEffect->SetTechnique( g_hTech[g_TechniqueIndex] ) ); break;
  768.             case 1: V( g_pEffect->SetTechnique( g_hTechShowBlurFactor ) ); break;
  769.             case 2: V( g_pEffect->SetTechnique( g_hTechShowUnmodified ) ); break;
  770.         }
  771.  
  772.         // Render the fullscreen quad on to the backbuffer
  773.         V( g_pEffect->Begin(&cPasses, 0) );
  774.         for (iPass = 0; iPass < cPasses; iPass++)
  775.         {
  776.             V( g_pEffect->BeginPass(iPass) );
  777.             V( pd3dDevice->SetFVF(VERTEX::FVF) );
  778.             V( pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Vertex, sizeof(VERTEX)) );
  779.             V( g_pEffect->EndPass() );
  780.         }
  781.         V( g_pEffect->End() );
  782.  
  783.         V( g_HUD.OnRender( fElapsedTime ) );
  784.         V( g_SampleUI.OnRender( fElapsedTime ) );
  785.  
  786.         // Render the text
  787.         RenderText();
  788.  
  789.         // End the scene.
  790.         pd3dDevice->EndScene();
  791.     }
  792. }
  793.  
  794.  
  795. //--------------------------------------------------------------------------------------
  796. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  797. // efficient text rendering.
  798. //--------------------------------------------------------------------------------------
  799. void RenderText()
  800. {
  801.     // The helper object simply helps keep track of text position, and color
  802.     // and then it calls pFont->DrawText( g_pSprite, strMsg, -1, &rc, DT_NOCLIP, g_clr );
  803.     // If NULL is passed in as the sprite object, then it will work however the 
  804.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  805.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  806.  
  807.     // Output statistics
  808.     txtHelper.Begin();
  809.     txtHelper.SetInsertionPos( 5, 5 );
  810.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  811.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  812.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  813.  
  814.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  815.  
  816.     switch( g_nShowMode )
  817.     {
  818.         case 0: txtHelper.DrawFormattedTextLine( L"Technique: %S", g_TechniqueNames[g_TechniqueIndex] ); break;
  819.         case 1: txtHelper.DrawTextLine( L"Technique: ShowBlurFactor" ); break;
  820.         case 2: txtHelper.DrawTextLine( L"Technique: ShowUnmodified" ); break;
  821.     }
  822.  
  823.     txtHelper.DrawFormattedTextLine( L"Focal Plane: (%0.1f,%0.1f,%0.1f,%0.1f)", g_vFocalPlane.x, g_vFocalPlane.y, g_vFocalPlane.z, g_vFocalPlane.w );
  824.  
  825.     
  826.     // Draw help
  827.     if( g_bShowHelp )
  828.     {
  829.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  830.         txtHelper.SetInsertionPos( 2, pd3dsdBackBuffer->Height-15*6 );
  831.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  832.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  833.  
  834.         txtHelper.SetInsertionPos( 20, pd3dsdBackBuffer->Height-15*5 );
  835.         txtHelper.DrawTextLine( L"Look: Left drag mouse\n"
  836.                                 L"Move: A,W,S,D or Arrow Keys\n"
  837.                                 L"Move up/down: Q,E or PgUp,PgDn\n"
  838.                                 L"Reset camera: End\n" );
  839.     }
  840.     else
  841.     {
  842.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  843.         txtHelper.DrawTextLine( L"Press F1 for help" );
  844.     }
  845.     txtHelper.End();
  846. }
  847.  
  848.  
  849. //--------------------------------------------------------------------------------------
  850. // Before handling window messages, the sample framework passes incoming windows 
  851. // messages to the application through this callback function. If the application sets 
  852. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  853. //--------------------------------------------------------------------------------------
  854. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  855. {
  856.     // Give the dialogs a chance to handle the message first
  857.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  858.     if( *pbNoFurtherProcessing )
  859.         return 0;
  860.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  861.     if( *pbNoFurtherProcessing )
  862.         return 0;
  863.  
  864.     // Pass all remaining windows messages to camera so it can respond to user input
  865.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  866.  
  867.     return 0;
  868. }
  869.  
  870.  
  871. //--------------------------------------------------------------------------------------
  872. // As a convenience, the sample framework inspects the incoming windows messages for
  873. // keystroke messages and decodes the message parameters to pass relevant keyboard
  874. // messages to the application.  The framework does not remove the underlying keystroke 
  875. // messages, which are still passed to the application's MsgProc callback.
  876. //--------------------------------------------------------------------------------------
  877. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  878. {
  879.     if( bKeyDown )
  880.     {
  881.         switch( nChar )
  882.         {
  883.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  884.         }
  885.     }
  886. }
  887.  
  888.  
  889. //--------------------------------------------------------------------------------------
  890. // Handles the GUI events
  891. //--------------------------------------------------------------------------------------
  892. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  893. {
  894.     switch( nControlID )
  895.     {
  896.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  897.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  898.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  899.  
  900.         case IDC_CHANGE_TECHNIQUE: 
  901.         {
  902.             DWORD OriginalTechnique = g_TechniqueIndex;
  903.             do
  904.             {
  905.                 g_TechniqueIndex++;
  906.  
  907.                 if (g_TechniqueIndex == g_TechniqueCount)
  908.                 {
  909.                     g_TechniqueIndex = 0;
  910.                 }
  911.  
  912.                 D3DXHANDLE hTech = g_pEffect->GetTechniqueByName(g_TechniqueNames[g_TechniqueIndex]);
  913.                 if (SUCCEEDED(g_pEffect->ValidateTechnique(hTech)))
  914.                 {
  915.                     break;
  916.                 }
  917.             } while(OriginalTechnique != g_TechniqueIndex);
  918.  
  919.             UpdateTechniqueSpecificVariables( DXUTGetBackBufferSurfaceDesc() );
  920.             break;
  921.         }
  922.  
  923.         case IDC_CHANGE_SCENE:     
  924.         {
  925.             g_nCurrentScene %= 2;
  926.             g_nCurrentScene++;
  927.  
  928.             switch( g_nCurrentScene )
  929.             {
  930.                 case 1:
  931.                 {
  932.                     D3DXVECTOR3 vecEye(0.75f, 0.8f, -2.3f);
  933.                     D3DXVECTOR3 vecAt (0.2f, 0.75f, -1.5f);
  934.                     g_Camera.SetViewParams( &vecEye, &vecAt );
  935.                     break;
  936.                 }
  937.  
  938.                 case 2:
  939.                 {
  940.                     D3DXVECTOR3 vecEye(0.0f, 0.0f, -3.0f);
  941.                     D3DXVECTOR3 vecAt (0.0f, 0.0f, 0.0f);
  942.                     g_Camera.SetViewParams( &vecEye, &vecAt );
  943.                     break;
  944.                 }
  945.             }
  946.             break;
  947.         }
  948.  
  949.         case IDC_CHANGE_FOCAL:
  950.         {    
  951.             WCHAR sz[100];
  952.             g_vFocalPlane.w = -g_SampleUI.GetSlider( IDC_CHANGE_FOCAL )->GetValue() / 10.0f;
  953.             _snwprintf( sz, 100, L"Focal Distance: %0.2f", -g_vFocalPlane.w ); sz[99] = 0;
  954.             g_SampleUI.GetStatic( IDC_CHANGE_FOCAL_STATIC )->SetText( sz );
  955.             UpdateTechniqueSpecificVariables( DXUTGetBackBufferSurfaceDesc() );
  956.             break;
  957.         }
  958.  
  959.         case IDC_SHOW_NORMAL:
  960.             g_nShowMode = 0;
  961.             break; 
  962.  
  963.         case IDC_SHOW_BLUR:
  964.             g_nShowMode = 1;
  965.             break;
  966.  
  967.         case IDC_SHOW_UNBLURRED:
  968.             g_nShowMode = 2;
  969.             break;
  970.  
  971.         case IDC_CHANGE_BLUR:
  972.         {
  973.             WCHAR sz[100];
  974.             g_fBlurConst = g_SampleUI.GetSlider( IDC_CHANGE_BLUR )->GetValue() / 10.0f;
  975.             _snwprintf( sz, 100, L"Blur Factor: %0.2f", g_fBlurConst ); sz[99] = 0;
  976.             g_SampleUI.GetStatic( IDC_CHANGE_BLUR_STATIC )->SetText( sz );
  977.             UpdateTechniqueSpecificVariables( DXUTGetBackBufferSurfaceDesc() );
  978.             break;
  979.         }
  980.     }
  981. }
  982.  
  983.  
  984. //--------------------------------------------------------------------------------------
  985. // This callback function will be called immediately after the Direct3D device has 
  986. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  987. // in the OnResetDevice callback should be released here, which generally includes all 
  988. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  989. // information about lost devices.
  990. //--------------------------------------------------------------------------------------
  991. void CALLBACK OnLostDevice()
  992. {
  993.     if( g_pFont )
  994.         g_pFont->OnLostDevice();
  995.     if( g_pEffect )
  996.         g_pEffect->OnLostDevice();
  997.     SAFE_RELEASE(g_pTextSprite);
  998.     SAFE_RELEASE(g_pFullScreenTextureSurf);
  999.     SAFE_RELEASE(g_pFullScreenTexture);
  1000.     SAFE_RELEASE(g_pRenderToSurface);
  1001. }
  1002.  
  1003.  
  1004. //--------------------------------------------------------------------------------------
  1005. // This callback function will be called immediately after the Direct3D device has 
  1006. // been destroyed, which generally happens as a result of application termination or 
  1007. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1008. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1009. //--------------------------------------------------------------------------------------
  1010. void CALLBACK OnDestroyDevice()
  1011. {
  1012.     SAFE_RELEASE(g_pEffect);
  1013.     SAFE_RELEASE(g_pFont);
  1014.  
  1015.     SAFE_RELEASE(g_pFullScreenTextureSurf);
  1016.     SAFE_RELEASE(g_pFullScreenTexture);
  1017.     SAFE_RELEASE(g_pRenderToSurface);
  1018.  
  1019.     SAFE_RELEASE(g_pScene1Mesh);
  1020.     SAFE_RELEASE(g_pScene1MeshTexture);
  1021.     SAFE_RELEASE(g_pScene2Mesh);
  1022.     SAFE_RELEASE(g_pScene2MeshTexture);
  1023. }
  1024.  
  1025.  
  1026.  
  1027.